#include "RewardsModel.h"

#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <qjsonarray.h>
#include <qjsonobject.h>

RewardsModel::RewardsModel(QObject *parent)
    : QAbstractListModel{parent}
{
    m_roleNames[NameRole] = "name";
    m_roleNames[Points] = "points";

    QFile file(getDataFilePath());
    if (file.exists()) {
        if (!loadFromJsonFile()) {
            qWarning() << "Failed to load task data from file, initializing with empty task list";
            createInitialJsonFile();
        }
    } else {
        createInitialJsonFile();
    }
}

void RewardsModel::addReward(QString text, int points)
{
    beginInsertRows(QModelIndex(), m_rewards.size(), m_rewards.size());
    m_rewards.append(Reward(text, points));
    endInsertRows();
    saveRewardData();
}

void RewardsModel::removeReward(int index)
{
    if (index < 0 || index >= m_rewards.size())
        return;

    beginRemoveRows(QModelIndex(), index, index);
    m_rewards.remove(index);
    endRemoveRows();
    saveRewardData();
}

void RewardsModel::exchangeReward(int index)
{
    removeReward(index);
}

void RewardsModel::saveRewardData()
{
    QJsonArray rewardsArray;

    for (const Reward &reward : m_rewards) {
        rewardsArray.append(reward.toJson());
    }

    QJsonObject jsonObj;
    jsonObj["rewards"] = rewardsArray;
    jsonObj["version"] = "1.0";

    QJsonDocument doc(jsonObj);
    QFile file(getDataFilePath());

    if (file.open(QIODevice::WriteOnly)) {
        file.write(doc.toJson());
        file.close();
        qDebug() << "Task data saved successfully, task count:" << m_rewards.size();
    } else {
        qWarning() << "Failed to save task data:" << file.errorString();
    }
}

void RewardsModel::loadRewardData()
{
    if (loadFromJsonFile()) {
        qDebug() << "Reward data loaded successfully, Reward count:" << m_rewards.size();
    } else {
        qWarning() << "Failed to load task data";
    }
}

int RewardsModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_rewards.count();
}

QVariant RewardsModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() < 0 || index.row() >= m_rewards.size())
        return QVariant();

    const Reward &reward = m_rewards.at(index.row());

    switch (role) {
    case NameRole:
        return reward.name;
    case Points:
        return reward.points;
    default:
        return QVariant();
    }

}

QHash<int, QByteArray> RewardsModel::roleNames() const
{
    return m_roleNames;
}

QString RewardsModel::getDataFilePath()
{
    QString dataDir = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
    QDir dir(dataDir);
    if (!dir.exists()) {
        dir.mkpath(".");
    }
    return dir.filePath("rewardsdata.json");
}

void RewardsModel::createInitialJsonFile()
{
    QJsonArray rewardsArray;

    QJsonObject jsonObj;
    jsonObj["rewards"] = rewardsArray;
    jsonObj["version"] = "1.0";

    QJsonDocument doc(jsonObj);
    QFile file(getDataFilePath());

    if (file.open(QIODevice::WriteOnly)) {
        file.write(doc.toJson());
        file.close();
        qDebug() << "Initial reward data file created successfully";
    } else {
        qWarning() << "Failed to create initial reward data file:" << file.errorString();
    }
}

bool RewardsModel::loadFromJsonFile()
{
    QFile file(getDataFilePath());

    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Failed to open task data file for reading:" << file.errorString();
        return false;
    }

    QByteArray data = file.readAll();
    file.close();

    QJsonDocument doc = QJsonDocument::fromJson(data);
    if (doc.isNull() || !doc.isObject()) {
        qWarning() << "Invalid JSON format in task data file";
        return false;
    }

    QJsonObject jsonObj = doc.object();
    QJsonArray rewardArray = jsonObj["rewards"].toArray();

    if (!m_rewards.isEmpty()) {
        beginRemoveRows(QModelIndex(), 0, m_rewards.size() - 1);
        m_rewards.clear();
        endRemoveRows();
    }

    if (m_rewards.isEmpty()) {
        beginInsertRows(QModelIndex(), 0, rewardArray.size() - 1);
        for (const QJsonValue &rewardValue : rewardArray) {
            QJsonObject rewardObj = rewardValue.toObject();
            m_rewards.append(Reward(rewardObj));
        }
        endInsertRows();
    }

    return true;
}
